using System;
using System.Diagnostics;
using UnityEngine;
using Debug = UnityEngine.Debug;
using static WinApi;
using System.Runtime.InteropServices;

public class User32Controller : IDisposable
{
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
    // 窗口句柄
    IntPtr _hwnd;
    Rect _originalRect; // 最大化前的窗口位置和大小

    public bool IsBlack = false;
    private const int DragRegionHeight = 30; // 可调整大小的区域高度

    // 拖拽相关变量
    bool _isDragging;
    POINT _dragStartMousePos; // 拖拽开始时的鼠标位置
    Rect _dragStartWindowRect; // 拖拽开始时的窗口位置

    // 窗口过程相关变量（新增）
    IntPtr _originalWndProc = IntPtr.Zero; // 原始窗口过程
    WNDPROC _customWndProc; // 自定义窗口过程委托（防止GC回收）

    // user32 API 常量
    const int SW_MAXIMIZE = 3;
    const int SW_MINIMIZE = 6;
    const int SW_RESTORE = 9;
    const uint SPI_GETWORKAREA = 0x0030;
    const uint SWP_NOSIZE = 0x0001;
    const uint SWP_NOMOVE = 0x0002;
    const uint SWP_NOZORDER = 0x0004;
    const uint SWP_NOACTIVATE = 0x0010;
    const int GWL_STYLE = -16;
    const int GWL_EXSTYLE = -20;
    const int GWL_WNDPROC = -4; // 窗口过程索引
    const int WS_CAPTION = 0x00C00000;
    const int WS_BORDER = 0x00800000;
    const int WS_THICKFRAME = 0x00040000;
    const int WS_SYSMENU = 0x00080000;
    const int WS_MINIMIZEBOX = 0x00020000;
    const int WS_MAXIMIZEBOX = 0x00010000;
    const int SWP_FRAMECHANGED = 0x0020;//表示窗口框架已更改
    const uint MONITOR_DEFAULTTONEAREST = 0x00000002; // 多屏幕：获取最近的显示器
    const uint WM_SYSCOMMAND = 0x0112; // 系统命令消息
    const int SC_MAXIMIZE = 0xF030; // 最大化系统命令


    // 扩展窗口样式
    const int WS_EX_DLGMODALFRAME = 0x00000001;
    const int WS_EX_CLIENTEDGE = 0x00000200;

    // DWM 常量（新增）
    private const int DWMWA_NCRENDERING_POLICY = 2;
    private const int DWMWA_USE_IMMERSIVE_DARK_MODE = 20;
    private const int DWMWA_WINDOW_CORNER_PREFERENCE = 33;
    private const int DWMNCRP_ENABLED = 2;
    private const int DWMNCRP_DISABLED = 1;
    private const int DWMWCP_DEFAULT = 0;
    private const int DWMWCP_DONOTROUND = 1;

    // 窗口消息常量（新增）
    const uint WM_NCCALCSIZE = 0x0083;
    const uint WM_NCHITTEST = 0x0084;
    const uint HTCLIENT = 0x01;
    const uint HTCAPTION = 0x02;
    const uint HTTOP = 0x03;
    const uint HTTOPLEFT = 0x04;
    const uint HTTOPRIGHT = 0x05;
    const uint HTLEFT = 0x0A;
    const uint HTRIGHT = 0x0B;
    const uint HTBOTTOM = 0x0F;
    const uint HTBOTTOMLEFT = 0x10;
    const uint HTBOTTOMRIGHT = 0x11;

    public User32Controller()
    {
        _hwnd = GetUnityMainWindowHandle();
        if (_hwnd == IntPtr.Zero)
        {
            Debug.LogError("无法获取窗口句柄");
            return;
        }
        // 初始化时保存原始窗口状态
        if (GetWindowRect(_hwnd, out RECT rect))
        {
            _originalRect = rect.ToRect();
        }

#if !UNITY_EDITOR
        // 注册自定义窗口过程（拦截系统消息）
        _customWndProc = new WNDPROC(CustomWindowProc);
        _originalWndProc = SetWindowLongPtr(_hwnd, GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(_customWndProc));
        // 应用现代窗口样式
        ApplyModernWindowStyle();
#endif
    }



    /// <summary>
    /// 应用方法4的现代窗口样式
    /// </summary>
    void ApplyModernWindowStyle()
    {
        if (_hwnd == IntPtr.Zero) return;

        try
        {
            // 1. 检查DWM组合是否启用
            bool isDwmEnabled;
            int dwmResult = DwmIsCompositionEnabled(out isDwmEnabled);

            if (dwmResult != 0 || !isDwmEnabled)
            {
                Debug.LogWarning("DWM composition is not enabled. Some visual effects may not work.");
            }

            // 2. 移除传统标题栏和边框
            int style = GetWindowLong(_hwnd, GWL_STYLE);

            // 移除标题栏但保留边框
            style &= ~WS_CAPTION;
            style |= WS_THICKFRAME; // 确保可调整大小        

            SetWindowLong(_hwnd, GWL_STYLE, style);

            // 4. 设置DWM边距（关键步骤 - 顶部设为0去除白色边框）
            MARGINS margins = new MARGINS
            {
                topHeight = 0,    // 顶部设为0去除白色边框
                leftWidth = 1,
                rightWidth = 1,
                bottomHeight = 1
            };

            DwmExtendFrameIntoClientArea(_hwnd, ref margins);

            // 5. 强制刷新窗口
            SetWindowPos(_hwnd, IntPtr.Zero, 0, 0, 0, 0,
                SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);

            Debug.Log("Modern window styling applied successfully");
        }
        catch (Exception e)
        {
            Debug.LogError($"Error applying window style: {e.Message}");
        }
    }




    /// <summary>
    /// 自定义窗口过程（拦截系统最大化消息）
    /// </summary>
    IntPtr CustomWindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
    {
        // 拦截系统最大化命令（包括Win+Up键触发的）
        switch (msg)
        {
            case WM_SYSCOMMAND:
                if (wParam.ToInt32() == SC_MAXIMIZE)
                {
                    Maximize();
                    return IntPtr.Zero;
                }
                break;

            case WM_NCCALCSIZE:
                // 完全移除非客户区
                if (wParam.ToInt32() == 1) // TRUE
                {
                    return IntPtr.Zero;
                }
                break;

            case WM_NCHITTEST:
                // 处理鼠标点击区域检测，实现拖拽和调整大小
                return HandleNCHitTest(lParam);
        }

        // 其他消息交给原始窗口过程处理
        return CallWindowProc(_originalWndProc, hWnd, msg, wParam, lParam);
    }

    /// <summary>
    /// 处理鼠标点击区域检测（实现拖拽和调整大小）
    /// </summary>
    private IntPtr HandleNCHitTest(IntPtr lParam)
    {
        if (!GetWindowRect(_hwnd, out RECT windowRect))
            return IntPtr.Zero;

        int x = (short)(lParam.ToInt32() & 0xFFFF);
        int y = (short)((lParam.ToInt32() >> 16) & 0xFFFF);

        // 定义边框大小（可调整大小的区域）- 增加到12像素确保容易点击
        int borderSize = 12;

        // 检查是否在可调整大小的边框区域
        bool left = x <= windowRect.Left + borderSize;
        bool right = x >= windowRect.Right - borderSize;
        bool top = y <= windowRect.Top + borderSize;
        bool bottom = y >= windowRect.Bottom - borderSize;

        // 角落区域 - 优先处理，确保缩放功能正常
        if (top && left) return (IntPtr)HTTOPLEFT;
        if (top && right) return (IntPtr)HTTOPRIGHT;
        if (bottom && left) return (IntPtr)HTBOTTOMLEFT;
        if (bottom && right) return (IntPtr)HTBOTTOMRIGHT;

        // 边缘区域 - 确保缩放功能正常
        if (left) return (IntPtr)HTLEFT;
        if (right) return (IntPtr)HTRIGHT;
        if (top) return (IntPtr)HTTOP;
        if (bottom) return (IntPtr)HTBOTTOM;

        // 只有在窗口顶部中央区域允许拖拽，避开边缘和角落
        int dragRegionTopMargin = 0;
        int dragRegionLeftMargin = 50;  // 左边距，避开左上角
        int dragRegionRightMargin = 50; // 右边距，避开右上角和系统按钮

        bool inTopRegion = y >= windowRect.Top && y <= windowRect.Top + dragRegionTopMargin;
        bool inHorizontalCenter = x >= windowRect.Left + dragRegionLeftMargin &&
                                 x <= windowRect.Right - dragRegionRightMargin;

        if (inTopRegion && inHorizontalCenter)
        {
            return (IntPtr)HTCAPTION;
        }

        // 其他情况交给系统处理，这样系统按钮和正常功能都能工作
        return (IntPtr)HTCLIENT;
    }


    /// <summary>
    /// 获取Unity主窗口句柄（复用WindowController逻辑）
    /// </summary>
    IntPtr GetUnityMainWindowHandle()
    {
        int processId = Process.GetCurrentProcess().Id;
        IntPtr hWnd = IntPtr.Zero;

        EnumWindows((hWnd1, lParam) =>
        {
            if (IsWindowVisible(hWnd1))
            {
                GetWindowThreadProcessId(hWnd1, out ulong windowProcessId);
                if (windowProcessId == (ulong)processId)
                {
                    hWnd = hWnd1;
                    return false;
                }
            }
            return true;
        }, IntPtr.Zero);

        return hWnd;
    }

    /// <summary>
    /// 最大化窗口
    /// </summary>
    public void Maximize()
    {
        if (_hwnd == IntPtr.Zero) return;

        // 保存当前窗口状态用于还原
        if (GetWindowRect(_hwnd, out RECT rect))
        {
            _originalRect = rect.ToRect();
        }

        // 1. 获取窗口当前中心点（用于定位所在屏幕）
        POINT windowCenter = new POINT
        {
            X = (rect.Left + rect.Right) / 2,
            Y = (rect.Top + rect.Bottom) / 2
        };

        // 2. 根据窗口中心点获取所在显示器句柄
        IntPtr hMonitor = MonitorFromPoint(windowCenter, MONITOR_DEFAULTTONEAREST);
        if (hMonitor == IntPtr.Zero)
        {
            // 失败时降级使用主屏幕
            Debug.LogWarning("获取当前显示器失败，使用主屏幕");
            if (SystemParametersInfo(SPI_GETWORKAREA, 0, out RECT mainWorkArea, 0))
            {
                SetWindowToWorkArea(mainWorkArea);
            }
            else
            {
                ShowWindow(_hwnd, SW_MAXIMIZE);
            }
            return;
        }

        // 3. 获取当前显示器的工作区（排除任务栏）
        MONITORINFO monitorInfo = new MONITORINFO();
        monitorInfo.cbSize = Marshal.SizeOf(monitorInfo); // 必须初始化大小
        if (GetMonitorInfo(hMonitor, ref monitorInfo))
        {
            SetWindowToWorkArea(monitorInfo.rcWork);
        }
        else
        {
            // 获取显示器信息失败时降级
            ShowWindow(_hwnd, SW_MAXIMIZE);
        }
    }
    /// <summary>
    /// 将窗口设置到指定工作区（内部辅助方法）
    /// </summary>
    void SetWindowToWorkArea(RECT workArea)
    {
        SetWindowPos(_hwnd, IntPtr.Zero,
            workArea.Left, workArea.Top,
            workArea.Right - workArea.Left,
            workArea.Bottom - workArea.Top,
            SWP_NOZORDER | SWP_NOACTIVATE);
    }
    /// <summary>
    /// 最小化窗口
    /// </summary>
    public void Minimize()
    {
        if (_hwnd == IntPtr.Zero) return;
        ShowWindow(_hwnd, SW_MINIMIZE);
    }

    /// <summary>
    /// 还原窗口
    /// </summary>
    public void Restore()
    {
        if (_hwnd == IntPtr.Zero) return;

        ShowWindow(_hwnd, SW_RESTORE);

        // 恢复到最大化前的位置和大小

        SetWindowPos(_hwnd, IntPtr.Zero,
            (int)_originalRect.x, (int)_originalRect.y,
            (int)_originalRect.width, (int)_originalRect.height,
            SWP_NOZORDER | SWP_NOACTIVATE);

    }

    /// <summary>
    /// 开始拖拽窗口
    /// </summary>
    public void BeginDrag()
    {
        if (_hwnd == IntPtr.Zero) return;

        // 获取当前鼠标位置和窗口位置
        if (GetCursorPos(out POINT mousePos) && GetWindowRect(_hwnd, out RECT windowRect))
        {
            _dragStartMousePos = mousePos;
            _dragStartWindowRect = windowRect.ToRect();
            _isDragging = true;
        }
    }

    /// <summary>
    /// 拖拽窗口处理
    /// </summary>
    public void Drag()
    {
        if (!_isDragging || _hwnd == IntPtr.Zero) return;

        if (GetCursorPos(out POINT currentMousePos))
        {
            // 计算位移
            int deltaX = currentMousePos.X - _dragStartMousePos.X;
            int deltaY = currentMousePos.Y - _dragStartMousePos.Y;

            // 设置新位置
            SetWindowPos(_hwnd, IntPtr.Zero,
                (int)_dragStartWindowRect.x + deltaX,
                (int)_dragStartWindowRect.y + deltaY,
                0, 0,
                SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
        }
    }

    /// <summary>
    /// 结束拖拽
    /// </summary>
    public void EndDrag()
    {
        _isDragging = false;
    }

    public void Dispose()
    {
        // 释放资源（如需要恢复窗口样式可在此处理）
        if (_hwnd != IntPtr.Zero && _originalWndProc != IntPtr.Zero)
        {
            SetWindowLongPtr(_hwnd, GWL_WNDPROC, _originalWndProc);
        }
        _hwnd = IntPtr.Zero;
    }
#endif
}